//****************************************************
//Sortierverfahrenvergleichs-App
//Autor: Timo Reichert
//
//Kunde: Herr Falke
//Erstelldatum: 24.09.2013 v.1.0.0
//
//Änderungen: 
//
//
//
//****************************************************

package fia12;

import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;

public class View extends JFrame {

	// Globale Variablen
	// Gui-Elemente
	private JPanel contentPane;
	private JTextField jTextFieldArraySize;
	private JButton jButtonRandomArray;
	private JButton jButtonBubblesort;
	private JTextArea textArea = new JTextArea();
	private JButton jButtonQuicksort;
	private JLabel jLabelArraySize;
	private JLabel jLabelTitleRandomArray;
	private JLabel jLabelTitleSortFunctions;
	private JButton jButtonExit;
	private JScrollPane scrollPane;
	private JLabel jLabelTitleElapsedTimeQuicksort;
	private JLabel jLabelElapsedTimeQuickSort;
	private JLabel jLabelTitleElapsedTimeBubblesort;
	private JLabel jLabelElapsedTimeBubblesort;

	// Arrays zum Sortieren (Original/Zwischenkopie)
	private int[] randomArray;
	private int[] savedArray;

	// *****************************************************
	// Main-Methode zum Starten der Gui
	// Eingabe : Java Standardparameter
	// Rückgabe: Keine
	// Ausgabe : Keine
	// *****************************************************
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					View frame = new View();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	// *****************************************************
	// Klasse : Erzeugen der Gui
	// Eingabe : Keine
	// Rückgabe: Keine
	// Ausgabe : Erzeugen einer visuellen Ein-und-Ausgabe-Oberfläche
	// *****************************************************
	public View() {
		// Main-Frame  Eigenschaften setzen
		setTitle("Sortierverfahrensvergleich-App");
		setResizable(false);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 592, 400);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);

		// Erzeugen des Buttons für das Zufallsarray
		jButtonRandomArray = new JButton("Zufallsfeld generieren");
		jButtonRandomArray.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				createRandomArray(
						Integer.parseInt(jTextFieldArraySize.getText()),
						Integer.parseInt(jTextFieldArraySize.getText()));
				jLabelElapsedTimeBubblesort.setText("Neue Messung");
				jLabelElapsedTimeQuickSort.setText("Neue Messung");
				textArea.setText(fillArrayInList(randomArray));
			}
		});
		jButtonRandomArray.setBounds(408, 69, 166, 23);
		contentPane.add(jButtonRandomArray);
		
		//Erzeugen des Buttons für Bubblesort
		jButtonBubblesort = new JButton("BubbleSort");
		jButtonBubblesort.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				if (null != randomArray) {
					
					savedArray = copyArray(randomArray);
					long startDate = System.nanoTime();
					long endDate;

					bubbleSort(savedArray);
					endDate = System.nanoTime();
					jLabelElapsedTimeBubblesort.setText(String
							.valueOf((endDate - startDate) / 1000));

					textArea.setText(textArea.getText() + "\n"
							+ "BubbleSort: Elapsed Time in Microseconds: "
							+ String.valueOf((endDate - startDate) / 1000));
					textArea.setText(textArea.getText() + "\n"
							+ fillArrayInList(savedArray));
				}
			}
		});
		jButtonBubblesort.setBounds(408, 244, 119, 23);
		contentPane.add(jButtonBubblesort);

		//Erzeugen des Buttons für Quicksort
		jButtonQuicksort = new JButton("Quicksort");
		jButtonQuicksort.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				savedArray = copyArray(randomArray);
				long startDate = System.nanoTime();
				long endDate;
				qsort(savedArray, 0, savedArray.length - 1);
				endDate = System.nanoTime();
				jLabelElapsedTimeQuickSort.setText(String
						.valueOf((endDate - startDate) / 1000));
				textArea.setText(textArea.getText() + "\n"
						+ "QickSort: Elapsed Time in Microseconds: "
						+ String.valueOf((endDate - startDate) / 1000));
				textArea.setText(textArea.getText() + "\n"
						+ fillArrayInList(savedArray));
			}
		});
		jButtonQuicksort.setBounds(408, 160, 119, 23);
		contentPane.add(jButtonQuicksort);

		jLabelArraySize = new JLabel("Feldl\u00E4nge");
		jLabelArraySize.setBounds(408, 44, 70, 14);
		contentPane.add(jLabelArraySize);

		//Erzeugen des Textfeldes für die Länge des Arrays
		jTextFieldArraySize = new JTextField();
		jTextFieldArraySize.addKeyListener(new KeyListener() {


			@Override
			public void keyReleased(KeyEvent e) {
				try {
					Integer.parseInt(jTextFieldArraySize.getText());
				} catch (NumberFormatException exception) {
					jTextFieldArraySize.setText("20");
				}
			}

			@Override
			public void keyTyped(KeyEvent e) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void keyPressed(KeyEvent e) {
				// TODO Auto-generated method stub
				
			}


		});
		jTextFieldArraySize.setText("20");
		jTextFieldArraySize.setBounds(465, 41, 109, 20);
		contentPane.add(jTextFieldArraySize);
		jTextFieldArraySize.setColumns(10);

		jLabelTitleRandomArray = new JLabel("Unsortierte Liste:");
		jLabelTitleRandomArray.setFont(new Font("Tahoma", Font.BOLD, 12));
		jLabelTitleRandomArray.setBounds(408, 7, 119, 23);
		contentPane.add(jLabelTitleRandomArray);

		jLabelTitleSortFunctions = new JLabel("Sortierfunktionen");
		jLabelTitleSortFunctions.setFont(new Font("Tahoma", Font.BOLD, 12));
		jLabelTitleSortFunctions.setBounds(408, 126, 119, 23);
		contentPane.add(jLabelTitleSortFunctions);

		jButtonExit = new JButton("Beenden");
		jButtonExit.setBounds(485, 337, 89, 23);
		jButtonExit.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				System.exit(getDefaultCloseOperation());
			}
		});
		contentPane.add(jButtonExit);

		scrollPane = new JScrollPane();
		scrollPane.setBounds(10, 10, 388, 350);
		contentPane.add(scrollPane);
		textArea.setWrapStyleWord(true);
		textArea.setLineWrap(true);

		textArea.setEditable(false);
		scrollPane.setViewportView(textArea);

		jLabelTitleElapsedTimeQuicksort = new JLabel("Zeit in Mikrosekunden:");
		jLabelTitleElapsedTimeQuicksort.setFont(new Font("Tahoma", Font.BOLD,
				11));
		jLabelTitleElapsedTimeQuicksort.setBounds(408, 194, 166, 14);
		contentPane.add(jLabelTitleElapsedTimeQuicksort);

		jLabelElapsedTimeQuickSort = new JLabel("keine Messung");
		jLabelElapsedTimeQuickSort.setBounds(432, 219, 142, 14);
		contentPane.add(jLabelElapsedTimeQuickSort);

		jLabelTitleElapsedTimeBubblesort = new JLabel("Zeit in Mikrosekunden:");
		jLabelTitleElapsedTimeBubblesort.setFont(new Font("Tahoma", Font.BOLD,
				11));
		jLabelTitleElapsedTimeBubblesort.setBounds(408, 278, 166, 14);
		contentPane.add(jLabelTitleElapsedTimeBubblesort);

		jLabelElapsedTimeBubblesort = new JLabel("keine Messung");
		jLabelElapsedTimeBubblesort.setBounds(432, 303, 142, 14);
		contentPane.add(jLabelElapsedTimeBubblesort);
	}

	// *****************************************************
	// Methode : Erstelle Kopie des Arrays
	// Eingabe : Array
	// Rückgabe: Keine
	// Ausgabe : Keine
	// *****************************************************		
	private int[] copyArray(int[] array) {
		int[] result = new int[array.length];
		for (int i = 0; i < array.length; i++) {
			result[i] = array[i];
		}
		return result;
	}

	// *****************************************************
	// Methode : Array aus Zufallszahlen erstellen
	// Eingabe : Länge des Arrays und Höchster Wert
	// Rückgabe: Keine
	// Ausgabe : Keine
	// *****************************************************		
	private void createRandomArray(int ArrayLength, int MaxInt) {
		randomArray = new int[ArrayLength];
		Random ttt = new Random();
		for (int i = 0; i < ArrayLength; i++) {
			randomArray[i] = ttt.nextInt(MaxInt);
		}

	}

	
	// *****************************************************
	// Methode : Array in String füllen
	// Eingabe : Array
	// Rückgabe: String-Kette
	// Ausgabe : Keine
	// *****************************************************		
	private String fillArrayInList(int[] array) {
		String result = new String();
		for (int i = 0; i < array.length; i++) {
			result += String.valueOf(array[i]) + "; ";
		}

		return result + "\n";
	}

	// *****************************************************
	// Methode : Vertauschen zweier Felder eines Arrays
	// Eingabe : Array, zu vertauschende Feldelemente
	// Rückgabe: Keine
	// Ausgabe : Keine
	// *****************************************************	
	private void swap(int[] array, int idx1, int idx2) {
		int tmp = array[idx1];
		array[idx1] = array[idx2];
		array[idx2] = tmp;
	}

	// *****************************************************
	// Methode : Bubblesort
	// Eingabe : Array
	// Rückgabe: Keine
	// Ausgabe : Keine
	// *****************************************************		
	private void bubbleSort(int[] tempArray) {
		Boolean MussteSortieren;
		for (int i = tempArray.length - 1; i > -1; i--) {
			MussteSortieren = false;
			for (int j = 0; j < i; j++) {
				if (tempArray[j] > tempArray[j + 1]) {
					int tempZahl = tempArray[j];
					tempArray[j] = tempArray[j + 1];
					tempArray[j + 1] = tempZahl;
					MussteSortieren = true;
				}
			}
			if (!MussteSortieren)
				break;
		}
	}

	// *****************************************************
	// Methode : Quicksort
	// Eingabe : Array, linkes und rechtes Feldelement
	// Rückgabe: Keine
	// Ausgabe : Keine
	// *****************************************************	
	private void qsort(int[] array, int le, int ri) {
		int lo = le, hi = ri;

		if (hi > lo) {
			// Pivotelement bestimmen
			int mid = array[(lo + hi) / 2];
			while (lo <= hi) {
				// Erstes Element suchen, das größer oder gleich dem
				// Pivotelement ist, beginnend vom linken Index
				while (lo < ri && array[lo] < mid)
					++lo;

				// Element suchen, das kleiner oder gleich dem
				// Pivotelement ist, beginnend vom rechten Index
				while (hi > le && array[hi] > mid)
					--hi;

				// Wenn Indexe nicht gekreuzt --> Inhalte vertauschen
				if (lo <= hi) {
					swap(array, lo, hi);
					++lo;
					--hi;
				}
			}
			// Linke Partition sortieren
			if (le < hi) {
				qsort(array, le, hi);
			}

			// Rechte Partition sortieren
			if (lo < ri) {
				qsort(array, lo, ri);
			}
		}
	}
}
